package com.hellobike.haxing.modules.product.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.hellobike.haxing.common.vo.Result;
import com.hellobike.haxing.modules.product.entity.*;
import com.hellobike.haxing.modules.product.mapper.*;
import com.hellobike.haxing.modules.product.model.PromotionGroupNojoinSku;
import com.hellobike.haxing.modules.product.service.IPromotionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 活动主信息
 * @Author: haxing-boot
 * @Date: 2020-01-23
 * @Version: V1.0
 */
@Service
public class PromotionServiceImpl extends ServiceImpl<PromotionMapper, Promotion> implements IPromotionService {

    @Autowired
    private PromotionMapper promotionMapper;
    @Autowired
    private PromotionGroupMapper promotionGroupMapper;
    @Autowired
    private PromotionFlashMapper promotionFlashMapper;

    @Autowired
    private PromotionGroupSkuMapper promotionGroupSkuMapper;
    @Autowired
    private ProductMapper productMapper;

    private void updateGroupNoJoin(Promotion promotion) {
        PromotionGroup promotionGroup = promotionGroupMapper.selectOne(new QueryWrapper<PromotionGroup>()
                .lambda().eq(PromotionGroup::getPromotionId, promotion.getId()).last("limit 1")
                .orderByDesc(PromotionGroup::getId));
        /**
         * 删除变更前的商品
         */
        boolean add = false;
        if (promotionGroup != null && !promotionGroup.getProductId().equals(promotion.getProductId())) {
            promotionGroupMapper.deleteById(promotionGroup.getId());
            add = true;
        }
        if (promotionGroup == null) {
            add = true;
        }
        if (add) {
            Product product = productMapper.selectById(promotion.getProductId());
            if (product != null) {
                Integer checked = promotionMapper.check(promotion.getId(), product.getId(), promotion.getBeginTime(), promotion.getEndTime());
                if (checked > 0) {
                    throw new RuntimeException("商品已经存在其它活动");
                }
                promotionGroup = new PromotionGroup();
                promotionGroup.setGroupType(2);
                promotionGroup.setProductName(product.getTitle());
                promotionGroup.setProductId(product.getId());
                promotionGroup.setPromotionId(promotion.getId());
                promotionGroup.setSpuCode(product.getSpuCode());
                promotionGroup.setStatus(1);
                promotionGroup.setSize(1);
                promotionGroup.setAutoComplete(0);
                promotionGroup.setTimeLimitRule(new JSONObject());
                promotionGroup.setSortIndex(1);
                promotionGroupMapper.insert(promotionGroup);
                for (PromotionGroupNojoinSku groupSkus : promotion.getGroupSkus()) {
                    PromotionGroupSku sku = new PromotionGroupSku();
                    sku.setSkuId(groupSkus.getSkuId());
                    sku.setStockInit(groupSkus.getStockInit());
                    sku.setStockLeft(sku.getStockInit());
                    sku.setUserBuyLimit(groupSkus.getUserBuyLimit());
                    sku.setGroupPrice(groupSkus.getGroupPrice());
                    sku.setGroupId(promotionGroup.getId());
                    promotionGroupSkuMapper.insert(sku);
                }
            }

        } else {
            List<PromotionGroupSku> promotionGroupSkus = promotionGroupSkuMapper.selectList(new QueryWrapper<PromotionGroupSku>()
                    .lambda().eq(PromotionGroupSku::getGroupId, promotionGroup.getId()));
            if (!CollectionUtils.isEmpty(promotionGroupSkus)) {
                Map<Long, PromotionGroupSku> promotionGroupSkuMap = promotionGroupSkus.stream()
                        .collect(Collectors.toMap(promotionGroupSku -> promotionGroupSku.getSkuId(), promotionGroupSku -> promotionGroupSku, (v1, v2) -> v1));
                if (!CollectionUtils.isEmpty(promotion.getGroupSkus())) {
                    for (PromotionGroupNojoinSku groupSkus : promotion.getGroupSkus()) {
                        /**
                         * 修改
                         */
                        if (promotionGroupSkuMap.containsKey(groupSkus.getSkuId())) {
                            PromotionGroupSku sku = promotionGroupSkuMap.get(groupSkus.getSkuId());
                            Integer left = groupSkus.getStockInit() - sku.getStockInit();
                            sku.setStockInit(groupSkus.getStockInit());
                            sku.setGroupPrice(groupSkus.getGroupPrice());
                            sku.setUserBuyLimit(groupSkus.getUserBuyLimit());
                            sku.setStockLeft(null);
                            promotionGroupSkuMapper.updateById(sku);
                            promotionGroupSkuMapper.incrementStockLeft(sku.getId(), left);
                            promotionGroupSkuMap.remove(sku.getSkuId());
                        } else {
                            PromotionGroupSku sku = new PromotionGroupSku();
                            sku.setSkuId(groupSkus.getSkuId());
                            sku.setStockInit(groupSkus.getStockInit());
                            sku.setUserBuyLimit(groupSkus.getUserBuyLimit());
                            sku.setGroupPrice(groupSkus.getGroupPrice());
                            sku.setGroupId(promotionGroup.getId());
                            sku.setStockLeft(sku.getStockInit());
                            promotionGroupSkuMapper.insert(sku);
                        }
                    }
                    if (promotionGroupSkuMap.size() > 0) {
                        for (PromotionGroupSku value : promotionGroupSkuMap.values()) {
                            promotionGroupSkuMapper.deleteById(value.getId());
                        }
                    }
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result savePromotion(Promotion promotion) {
//        //限时抢购活动判断同站点下不同场次时间段不能重叠
//        if (promotion.getType() == 2 && isTimeCrossInSameShop(promotion)) {
//            return Result.error("相同站点下不同场次限时抢购活动时间不可重叠");
//        }
        //相同站点下不同场次限时抢购活动开始时间不能相同
        if (promotion.getType() == 2 && isBeginTimeSameInSameShop(promotion)) {
            return Result.error("相同站点下不同场次限时抢购活动开始时间不能相同");
        }
        promotionMapper.insert(promotion);
        if (promotion.getType() == 4) {
            updateGroupNoJoin(promotion);
        }
        return Result.ok("添加成功！");
    }

    @Override
    public Result updatePromotion(Promotion promotion) {
//        //限时抢购活动判断同站点下不同场次时间段不能重叠
//        if (promotion.getType() == 2 && isTimeCrossInSameShop(promotion)) {
//            return Result.error("相同站点下不同场次限时抢购活动时间不可重叠");
//        }
        //相同站点下不同场次限时抢购活动开始时间不能相同
        if (promotion.getType() == 2 && isBeginTimeSameInSameShop(promotion)) {
            return Result.error("相同站点下不同场次限时抢购活动开始时间不能相同");
        }
        if (promotion.getType() == 4) {
            updateGroupNoJoin(promotion);
        }
        //检查与其他活动商品是否冲突
        if (promotion.getStatus() == 1) {
            LinkedHashSet<String> errorTips = checkProductConflicts(promotion);
            if (!CollectionUtils.isEmpty(errorTips)) {
                return Result.error("该活动无法设为开启状态，因以下原因： " + Joiner.on(' ').join(errorTips));
            }
        }
        promotionMapper.updateById(promotion);
        return Result.ok("编辑成功！");
    }

    //检查与其他活动商品是否冲突
    private LinkedHashSet<String> checkProductConflicts(Promotion promotion) {
        LinkedHashSet<String> errorTips = new LinkedHashSet<>();
        List<Long> productIdList = null;
        if (promotion.getType() == 1) {
            List<PromotionGroup> promotionGroupList = promotionGroupMapper.selectList(new QueryWrapper<PromotionGroup>().
                    lambda().eq(PromotionGroup::getPromotionId, promotion.getId()));
            productIdList = promotionGroupList.stream().map(PromotionGroup::getProductId).collect(Collectors.toList());
        } else if (promotion.getType() == 2) {
            List<PromotionFlash> promotionFlashList = promotionFlashMapper.selectList(new QueryWrapper<PromotionFlash>().lambda().eq(PromotionFlash::getPromotionId, promotion.getId()));
            productIdList = promotionFlashList.stream().map(PromotionFlash::getProductId).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(productIdList)) {
            return errorTips;
        }
        for (Long productId : productIdList) {
            //判断商品参加的活动时间是否重叠
            List<Promotion> productPromotions = promotionMapper.getProductPromotions(productId);
            if (productPromotions.size() > 0) {
                for (Promotion otherPromotion : productPromotions) {
                    if (otherPromotion.getId().equals(promotion.getId())) {
                        continue;
                    }
                    if (!(promotion.getBeginTime().after(otherPromotion.getEndTime()) || promotion.getEndTime().before(otherPromotion.getBeginTime()))) {
                        Product product = productMapper.selectById(productId);
                        errorTips.add("商品[" + product.getTitle() + "]同时参加了活动[" + otherPromotion.getName() + "];");
                    }
                }
            }
        }
        return errorTips;
    }

    //相同站点下不同场次限时抢购活动开始时间不能相同
    private boolean isBeginTimeSameInSameShop(Promotion promotion) {
        //查询开始时间一样的限时抢购活动
        QueryWrapper<Promotion> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Promotion::getType, 2).eq(Promotion::getStatus, 1).eq(Promotion::getBeginTime, promotion.getBeginTime());
        List<Promotion> promotions = promotionMapper.selectList(queryWrapper);
        for (Promotion otherPromotion : promotions) {
            if (otherPromotion.getId().equals(promotion.getId())) {//跳过自身
                continue;
            }
            //判断两个活动覆盖站点是否有重叠
            if (promotion.getAvailableType() == 0 || otherPromotion.getAvailableType() == 0) {//任意一场覆盖全部站点必然重叠
                return true;
            }
            //判断适用站点是否存在交集
            otherPromotion.getAvailableShops().retainAll(promotion.getAvailableShops());
            if (otherPromotion.getAvailableShops().size() > 0) {
                return true;
            }
        }
        return false;
    }

    //限时抢购活动判断同站点下不同场次时间段不能重叠
    private boolean isTimeCrossInSameShop(Promotion promotion) {
        //查询时间有重叠的限时抢购活动
        QueryWrapper<Promotion> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Promotion::getType, 2).eq(Promotion::getStatus, 1).gt(Promotion::getEndTime, promotion.getBeginTime()).lt(Promotion::getBeginTime, promotion.getEndTime());
        List<Promotion> promotions = promotionMapper.selectList(queryWrapper);
        for (Promotion otherPromotion : promotions) {
            if (otherPromotion.getId().equals(promotion.getId())) {//跳过自身
                continue;
            }
            //判断两个活动覆盖站点是否有重叠
            if (promotion.getAvailableType() == 0 || otherPromotion.getAvailableType() == 0) {//任意一场覆盖全部站点必然重叠
                return true;
            }
            //判断适用站点是否存在交集
            otherPromotion.getAvailableShops().retainAll(promotion.getAvailableShops());
            if (otherPromotion.getAvailableShops().size() > 0) {
                return true;
            }
        }
        return false;
    }
}
